package flex.cc.single.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;

import cn.hutool.core.date.DateUtil;
import flex.cc.PublicUtil;
import flex.cc.common.utils.CommonUtils;
import flex.cc.common.utils.HttpClientUtil;
import flex.cc.single.dao.SingleCouponTrackDao;
import flex.cc.single.dto.entity.SingleCouponTrackEntity;
import flex.cc.single.dto.entity.SingleOrderEntity;
import flex.cc.single.dto.entity.VerifyTaskEntity;
import flex.cc.single.service.DxVerifyService;
import flex.cc.single.service.SingleOrderService;
import flex.cc.single.service.SingleRecordService;
import flex.cc.single.service.VerifyTaskService;
import flex.cc.store.dto.entity.StoreCouponEntity;
import flex.cc.store.service.StoreCouponService;
import flex.cc.util.APIConfigUtil;

/**
 * 
 * @author R
 * @2022年3月31日  19:52:51
 * @desc 单项类服务核销通知实现层
 */
@Service("dxVerifyService")
@Transactional(rollbackFor = Exception.class)
public class DxVerifyServiceImpl implements DxVerifyService {

	private static final Logger logger = LoggerFactory.getLogger(DxVerifyServiceImpl.class);
	@Resource
	private SingleOrderService singleOrderService;
	@Resource
	private StoreCouponService couponService;
	@Resource
    private SingleRecordService singleRecordService;
    @Autowired
	private APIConfigUtil apiConfigUtil;
    @Autowired
	private SingleCouponTrackDao singleCouponTrackDao;
	@Resource
	private VerifyTaskService taskService;
	/**
	 * 
	 * @author R
	 * @2022年3月31日  19:52:51
	 * @desc 核销通知
	 */
	@SuppressWarnings("serial")
	@Override
	public Map<String, String> verifyNotice(String jsonInfo) {
		Date requestTime = new Date();
		logger.info("单项到店类上游核销开始==>"+DateUtil.format(requestTime, "yyyy-MM-dd HH:mm:ss"));
		Map<String, String> resultMap = new HashMap<>();
		String orderId = "";
		SingleOrderEntity orderVo = null;
		String requestBody = "";
		String result = "";
		try {
			JSONObject jsonObject = JSONObject.parseObject(jsonInfo);
			//卡券编码
			orderId = (String) jsonObject.get("order");
			if(PublicUtil.isEmpty(orderId)) {
				resultMap.put("code", "01");
				resultMap.put("msg", "卡券编码不能为空");
			}else{
				StoreCouponEntity couponEntity = couponService.queryByCouponNum(orderId);
				
				//根据订单号(卡券码)查询对应信息，拼装上游核销接口报文
				Map<String, Object> orderParam = new HashMap<String, Object>();
				orderParam.put("orderId", orderId);
				orderVo = singleOrderService.getOneByParams(orderParam);
				if (orderVo == null) {
					resultMap.put("code", "01");
					resultMap.put("msg", "卡券不存在");
					saveTrack(couponEntity, "2", "卡券不存在", "0", "下游核销通知接口");
				}else{
					//00-预约失败、01-预约成功、02-派单成功、03-司机已到达、04-服务完成、05-预约取消、06-取消核销
					String status = orderVo.getStatus();
					String serviceType = orderVo.getServiceType();//服务类型,1-安全检测；2-代办年检；3-代驾 ；4-洗车
					if (!"4".equals(serviceType)) {
						resultMap.put("code", "01");
						resultMap.put("msg", "非到店类卡券，核销失败");
						saveTrack(couponEntity, "2", "非到店类卡券，核销失败", "0", "下游核销通知接口");
					}else if ("04".equals(status) || "06".equals(status)) {
						resultMap.put("code", "01");
						resultMap.put("msg", "此卡券已核销");
						saveTrack(couponEntity, "2", "此卡券已核销", "0", "下游核销通知接口");
					}else{
						saveTrack(couponEntity, "2", "核销通知成功", "1", "下游核销通知接口");
						String verifyDate = (String) jsonObject.get("date"); //核销时间
						Map<String, Object> body = new HashMap<String, Object>();
						Map<String, Object> userInfo = new HashMap<String, Object>(); //用户信息
						userInfo.put("customerCode", orderVo.getCustomerCode());//客户号
						userInfo.put("id", orderVo.getOrderNo()); //发送卡券时唯一id
						userInfo.put("cardCode", orderVo.getOrderId()); //卡券编码
						userInfo.put("cardStatus", "3");//卡券状态，1-预约 2-取消 3-核销
						userInfo.put("carServiceType", serviceType);//服务类型，1-安全检测；2-代办年检；3-代驾 ；4-洗车
						
						Map<String, Object> businessInfo = new HashMap<String, Object>(); //业务信息
						businessInfo.put("remarks", ""); 
						
						body.put("userInfo", userInfo);
						body.put("businessInfo", businessInfo);
						requestBody = CommonUtils.toJSONString(body);
						
						String verifyUrl = apiConfigUtil.getSingleApiConfig("verifyUrl");
						String merchant = apiConfigUtil.getSingleApiConfig("merchant");
						String businessType = apiConfigUtil.getSingleApiConfig("businessType");
						String signKey = apiConfigUtil.getSingleApiConfig("signKey");
						//生成签名
						String sign = DigestUtils.md5Hex((signKey + requestBody).getBytes("UTF-8"));
						
						verifyUrl = verifyUrl+"?merchant="+merchant+"&businessType="+businessType+"&sign="+sign;
						String resultCode = "1";  //响应码:1-成功
						try {
							result = HttpClientUtil.sendHttpPostText(verifyUrl, requestBody, new HashMap<String, String>(){{
					            put("Content-Type", "text/plain;charset=UTF-8");
					        }});
							Date responseTime = new Date();
							logger.info("单项到店类上游核销结果==>"+result);
							JSONObject resultJson = JSONObject.parseObject(result);
							resultCode = (String) resultJson.get("resultCode"); //响应码
							String resultMessage = (String) resultJson.get("resultMessage"); //结果描述
							if(resultCode.equals("1")){
								saveTrack(couponEntity, "1", "上游核销成功", "1", "上游核销接口");
								resultMap.put("code", "00");
								resultMap.put("msg", "成功");
								//变更卡券、订单的状态：t_store_coupon、t_single_order_main
								Map<String,Object> coupon_params = new HashMap<String,Object>();
								coupon_params.put("couponNum", orderId);//卡券编码
								coupon_params.put("status", "3"); //3-已使用（核销完成）
								coupon_params.put("checkDate", verifyDate);//核销时间
								coupon_params.put("updateTime", new Date());
								couponService.updateByParam(coupon_params);
								Map<String,Object> order_params = new HashMap<String,Object>();
								order_params.put("id", orderVo.getId());
								order_params.put("status", "04");//服务完成
								order_params.put("updateTime", new Date());
								singleOrderService.updateByParams(order_params);
								saveTrack(couponEntity, "1", "核销成功", "2", "上游核销接口");
							}else{
								saveTrack(couponEntity, "1", resultMessage, "2", "上游核销接口");
								resultMap.put("code", "01");
								resultMap.put("msg", resultMessage);
								resultCode = "2";
							}
							//保存日志：t_single_record
							singleRecordService.saveSingleRecord(orderId, orderVo.getOrderNo(), requestTime, responseTime, "单项到店类上游核销接口", 
									resultCode.equals("SUCCESS")?"0":"1", resultCode.equals("SUCCESS")?"核销成功":resultMessage, requestBody, requestBody, result, result);
						} catch (Exception e) {
							resultCode = "2";
						}
						//add W 2022年4月6日09:46:21 根据核销结果，操作t_store_verify_task，定时复推上游核销通知任务---start
				        VerifyTaskEntity taskVo = new VerifyTaskEntity();
				        if("1".equals(resultCode)){
				        	taskVo.setCouponNum(orderId);
				        	taskVo.setStatus(0); //核销结果：0-成功、1-失败
				        	taskVo.setUpdateTime(new Date());
				        	taskService.update(taskVo);
				        }else{
				        	//核销失败，根据卡券码判断t_store_verify_task中是否已存在，若不存在，则插入
				        	Map<String, Object> task_params = new HashMap<String, Object>();
				        	task_params.put("couponNum", orderId);
				        	VerifyTaskEntity vo = taskService.getOneByParams(task_params);
				        	if(PublicUtil.isEmpty(vo)){
				        		taskVo.setCouponNum(orderId);
				        		taskVo.setWriteOffUrl(verifyUrl);
				        		taskVo.setCardType("3");//1-服务包到店、2-服务包代驾、3-单项到店、4-单项代驾、5-健康护理
				        		taskVo.setRequestBody(requestBody);
				        		taskVo.setResponseBody(result);
				        		taskVo.setStatus(1); //核销结果：0-成功、1-失败
				        		taskVo.setCreateTime(new Date());
				        		taskService.insert(taskVo);
				        	}
				        }
				        //add W 2022年4月6日09:46:21 根据核销结果，操作t_store_verify_task，定时复推上游核销通知任务---end
					}
				}
			}
		} catch (Exception e) {
			logger.info("请求单项到店类核销接口异常==>"+e.getMessage());
			resultMap.put("code", "01");
			resultMap.put("msg", "请求核销接口异常");
			singleRecordService.saveSingleRecord(orderId, orderVo!=null?orderVo.getOrderNo():"", requestTime, new Date(),  
				"单项到店类上游核销接口","1", "请求核销接口异常", requestBody, requestBody, result, result);
		}
		logger.info("单项到店类上游核销结束==>"+DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
		return resultMap;
	}
	
	
	/**
	 * 
	 * @author R
	 * 2022年2月16日下午15:31:06
	 * @desc 单项代驾异步核销通知上游
	 */
	@SuppressWarnings("serial")
	@Async
	public void asyncVerify(String orderId, String orderNo) {
		Date requestTime = new Date();
		
		StoreCouponEntity couponEntity = couponService.queryByCouponNum(orderId);
		logger.info("单项代驾上游核销开始==>"+DateUtil.format(requestTime, "yyyy-MM-dd HH:mm:ss"));
		String requestBody = "";
		String result = "";
		try {
			//根据订单号(卡券码)查询对应信息，拼装上游核销接口报文
			Map<String, Object> orderParam = new HashMap<String, Object>();
			orderParam.put("orderId", orderId);
			SingleOrderEntity orderVo = singleOrderService.getOneByParams(orderParam);
			Map<String, Object> body = new HashMap<String, Object>();
			Map<String, Object> userInfo = new HashMap<String, Object>(); //用户信息
			userInfo.put("customerCode", orderVo.getCustomerCode());//客户号
			userInfo.put("id", orderVo.getOrderNo()); //发送卡券时唯一id
			userInfo.put("cardCode", orderVo.getOrderId()); //卡券编码
			userInfo.put("cardStatus", "3");//卡券状态，1-预约 2-取消 3-核销
			userInfo.put("carServiceType", "3");//服务类型，1-安全检测；2-代办年检；3-代驾 ；4-洗车
			
			Map<String, Object> businessInfo = new HashMap<String, Object>(); //业务信息
			//起始经度
			businessInfo.put("drivingStartLongitude", orderVo.getLongitude()); 
			//起始纬度
			businessInfo.put("drivingStartLatitude", orderVo.getLatitude()); 
			//起始地点
			businessInfo.put("drivingStartPoint", orderVo.getDeparture()); 
			//起始省
			businessInfo.put("drivingStartProvince", orderVo.getDepartureProvince()); 
			//起始市
			businessInfo.put("drivingStartCity", orderVo.getDepartureCity()); 
			//起始区
			businessInfo.put("drivingStartCounty", orderVo.getDepartureArea()); 
			//目标经度
			businessInfo.put("drivingEndLongitude", orderVo.getDeLongitude()); 
			//目标纬度
			businessInfo.put("drivingEndLatitude", orderVo.getDeLatitude()); 
			//目标地点
			businessInfo.put("drivingEndPoint", orderVo.getDestination()); 
			//目标省
			businessInfo.put("drivingEndprovince", orderVo.getDestinationProvince()); 
			//目标市
			businessInfo.put("drivingEndCity", orderVo.getDestinationCity()); 
			//目标区
			businessInfo.put("drivingEndCounty", orderVo.getDestinationArea()); 
			
			body.put("userInfo", userInfo);
			body.put("businessInfo", businessInfo);
			requestBody = CommonUtils.toJSONString(body);
			
			String verifyUrl = apiConfigUtil.getSingleApiConfig("verifyUrl");
			String merchant = apiConfigUtil.getSingleApiConfig("merchant");
			String businessType = apiConfigUtil.getSingleApiConfig("businessType");
			String signKey = apiConfigUtil.getSingleApiConfig("signKey");
			
			//生成签名
			String sign = DigestUtils.md5Hex((signKey + requestBody).getBytes("UTF-8"));
			
			verifyUrl = verifyUrl+"?merchant="+merchant+"&businessType="+businessType+"&sign="+sign;
			String resultCode = "1"; //响应码:1-成功
			try {
				result = HttpClientUtil.sendHttpPostText(verifyUrl, requestBody, new HashMap<String, String>(){{
		            put("Content-Type", "text/plain;charset=UTF-8");
		        }});
				Date responseTime = new Date();
				logger.info("单项到店类上游核销结果==>"+result);
				JSONObject resultJson = JSONObject.parseObject(result);
				resultCode = (String) resultJson.get("resultCode"); //响应码
				String resultMessage = (String) resultJson.get("resultMessage"); //结果描述
				if(resultCode.equals("1")){
					//变更卡券、订单的状态：t_store_coupon、t_single_order_main
					Map<String,Object> coupon_params = new HashMap<String,Object>();
					coupon_params.put("couponNum", orderId);//卡券编码
					coupon_params.put("status", "3"); //3-已使用（核销完成）
					coupon_params.put("checkDate", new Date());//核销时间
					coupon_params.put("updateTime", new Date());
					couponService.updateByParam(coupon_params);
					Map<String,Object> order_params = new HashMap<String,Object>();
					order_params.put("id", orderVo.getId());
					order_params.put("status", "04");//服务完成
					order_params.put("updateTime", new Date());
					singleOrderService.updateByParams(order_params);
				}else{
					resultCode = "2";
				}
				//保存日志：t_single_record
				singleRecordService.saveSingleRecord(orderId, orderVo.getOrderNo(), requestTime, responseTime, "单项代驾类上游核销接口", 
						resultCode, resultCode.equals("1")?"核销成功":resultMessage, null, requestBody, null, result);
				
				saveTrack(couponEntity, "1", "上游核销通知接口失败---密码加密或数字签名异常", "0", "上游核销接口");
			} catch (Exception e) {
				resultCode = "2";
			}
			//add W 2022年4月6日09:46:21 根据核销结果，操作t_store_verify_task，定时复推上游核销通知任务---start
	        VerifyTaskEntity taskVo = new VerifyTaskEntity();
	        if("1".equals(resultCode)){
	        	taskVo.setCouponNum(orderId);
	        	taskVo.setStatus(0); //核销结果：0-成功、1-失败
	        	taskVo.setUpdateTime(new Date());
	        	taskService.update(taskVo);
	        }else{
	        	//核销失败，根据卡券码判断t_store_verify_task中是否已存在，若不存在，则插入
	        	Map<String, Object> task_params = new HashMap<String, Object>();
	        	task_params.put("couponNum", orderId);
	        	VerifyTaskEntity vo = taskService.getOneByParams(task_params);
	        	if(PublicUtil.isEmpty(vo)){
	        		taskVo.setCouponNum(orderId);
	        		taskVo.setWriteOffUrl(verifyUrl);
	        		taskVo.setCardType("4");//1-服务包到店、2-服务包代驾、3-单项到店、4-单项代驾、5-健康护理
	        		taskVo.setRequestBody(requestBody);
	        		taskVo.setResponseBody(result);
	        		taskVo.setStatus(1); //核销结果：0-成功、1-失败
	        		taskVo.setCreateTime(new Date());
	        		taskService.insert(taskVo);
	        	}
	        }
	        //add W 2022年4月6日09:46:21 根据核销结果，操作t_store_verify_task，定时复推上游核销通知任务---end
			
		} catch (Exception e) {
			logger.info("请求单项非到店类核销接口异常==>"+e.getMessage());
			singleRecordService.saveSingleRecord("orderId", "orderNo", requestTime, new Date(),  
				"单项非到店类上游核销接口","1", "请求核销接口异常", null, requestBody, null, result);
			saveTrack(couponEntity, "1", "请求单项非到店类上游核销接口异常", "0", "单项非到店类上游核销接口");
		}
		logger.info("单项非到店类上游核销结束==>"+DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
	}
	
	/**
	 * 新增卡券使用轨迹
	 * @param couponEntity  卡券信息
	 * @param trackType 轨迹类型：0-车服内部，1-与上游交互，2-与下游交互，3-与商户端交互
	 * @param trackDesc 轨迹描述
	 * @param result 接口请求结果：0-失败，1-成功
	 * @param creater
	 */
	 private void saveTrack(StoreCouponEntity couponEntity, String trackType, String trackDesc, String result, String creater){
		 Date d = new Date();
		 SingleCouponTrackEntity vo = new SingleCouponTrackEntity(couponEntity.getId(),couponEntity.getCouponNum(),
				 trackType,trackDesc,couponEntity.getStatus(),result);
		 vo.setIsDelete(0);
		 vo.setCreateTime(d);
		 vo.setCreater(creater);
		 vo.setUpdateTime(d);
		 vo.setUpdater(creater);
		 singleCouponTrackDao.insert(vo);	        
	 }	
}
